#region

using System;
using Gurock.SmartInspect;
using Microsoft.Practices.Unity.InterceptionExtension;

#endregion

namespace SmartInspect.Extensions.Unity
{
    public class SiWatchHandler : SiBaseHandler
    {
        private Session _session;
        public string ParameterName { private get; set; }

        /// <summary>
        ///   Add the HashCode of the instance to the parameter name.<br />To make
        ///   the watch name unqiue for all object instances, simply set this to true.
        /// </summary>
        public bool IncludeHashCode { private get; set; }

        public override IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
        {
            _session = input.Target.GetLogger();
            StartCallHandlerInvoke(input, _session);
            CheckAttributeUsage(input);
            string parameterName = GetParameterName(input);
            _session.Watch(parameterName, input.Arguments[0]);
            IMethodReturn ret = getNext().Invoke(input, getNext);
            StopCallHandlerInvoke(input, _session);
            return ret;
        }

        private void CheckAttributeUsage(IMethodInvocation input)
        {
            if((!input.MethodBase.Name.StartsWith("set_") && !input.MethodBase.Name.StartsWith("get_")) ||
                input.Arguments.Count != 1)
            {
                var exc = new NotImplementedException("You can use SiWatch only for property accessor methods");
                _session.LogException(exc);
                throw exc;
            }
        }

        private string GetParameterName(IMethodInvocation input)
        {
            return String.Format("{0}{1}",
                (IncludeHashCode ? String.Format("#{0}.", input.Target.GetHashCode()) : ""),
                string.IsNullOrEmpty(ParameterName) ? input.MethodBase.Name.Substring(4) : ParameterName
                );
        }
    }
}